package adsi.server;

import adsi.persistence.*;
import org.json.*;
import java.util.*;
import adsi.domain.*;
import adsi.utils.*;

public class LinesLogic {

    private final static LinesLogic instance = new LinesLogic();
    private DataServiceImpl ds;

    private LinesLogic() {
        ds = DataServiceImpl.getInstance();
    }

    public static LinesLogic getInstance() {
        return instance;
    }

    public boolean hasValidParameters(String[] keys, JSONObject parameters) throws JSONException {
        StringBuilder message = new StringBuilder();
        Map<String, String> types = new HashMap();
        Map<String, Object> params = new HashMap();

        types.put("id", "int");
        types.put("description", "String");
        types.put("drop-date", "date");
        types.put("available-date", "date");
        types.put("equipment", "String");
        types.put("maintenance", "String");
        types.put("created-from", "date");
        types.put("created-to", "date");
        types.put("dropped-from", "date");
        types.put("dropped-to", "date");
        types.put("available-from", "date");
        types.put("available-to", "date");
        types.put("vacant-from", "date");
        types.put("vacant-to", "date");
        types.put("occupied-from", "date");
        types.put("occupied-to", "date");

        try {
            for (String k : keys) {
                String t = types.get(k);
                params.put(k, null);

                System.out.println(k);

                if (t.equals("int")) {
                    params.put(k, parameters.getInt(k));
                } else if (t.equals("String")) {
                    params.put(k, parameters.getString(k));
                } else if (t.equals("date")) {
                    if (!"".equals(parameters.getString(k).trim())) {
                        params.put(k, DateTime.stringToCal(parameters.getString(k)));
                    } else {
                        // Fecha vacia sera tomada como opcional
                        params.remove(k);
                        parameters.put(k, "");
                    }
                } else if (t.equals("JSONArray")) {
                    params.put("description", null);
                    params.put("duration", null);
                    parameters.put("description", "");
                    parameters.put("duration", "");
                    JSONArray jsonList = parameters.getJSONArray(k);
                    String description = (String) jsonList.get(0);
                    params.put("description", description);
                    parameters.put("description", description);
                    int duration = Integer.parseInt((String) jsonList.get(1));
                    params.put("duration", duration);
                    parameters.put("duration", duration);
                }
            }
        } catch (Exception e) {
            System.out.println("Validation error");
            e.printStackTrace();
        }

        if (params.containsKey("id")) {
            Integer ID = (Integer) params.get("id");
            if (ID == null || ID != null && ID < 0) {
                message.append("La ID no debe ser menor a 0.\n");
            }
        }

        if (params.containsKey("description")) {
            String description = (String) params.get("description");
            if (description == null || description != null && description.trim().length() == 0) {
                message.append("La descripción no puede estar vacía.\n");
            }
        }

        if (params.containsKey("equipment")) {
            String tailNumber = (String) params.get("tail-number");
            if (tailNumber == null || tailNumber != null && tailNumber.length() != 6) {
                message.append("El formato para el Tail Number es incorrecto.\n");
            }
        }

        String[] dates = {"created-from", "created-to", "dropped-from", "dropped-to", "available-from",
            "available-to"
        };
        for (String d : dates) {
            Calendar cal = (Calendar) params.get(d);
            if (params.containsKey(d)) {
                //NOTA: agregar validacion???
                if (cal == null) {
                    message.append("El formato de fecha para '" + d + "' es incorrecto.\n");
                }
            }
        }

        String[] cumpolsoryDates = {"drop-date", "available-date"};
        for (String d : cumpolsoryDates) {
            if (params.containsKey("description")) { //create line            
                try {
                    String aux = parameters.getString(d);
                    if (aux.equals("")) {
                        throw new Exception("Incorrect date format.");
                    }
                } catch (Exception e) {
                    message.append("El formato de fecha para '" + d + "' es incorrecto.\n");
                }
            }
        }

        parameters.put("ERROR", message.toString());

        return message.toString().length() == 0;
    }

    public String create(JSONObject parameters) throws JSONException {
        String[] keys = {"description", "drop-date", "available-date"};

        if (hasValidParameters(keys, parameters)) {
            String description = parameters.getString("description");
            Calendar dropDate = DateTime.stringToCal(parameters.getString("drop-date"));
            Calendar availableDate = DateTime.stringToCal(parameters.getString("available-date"));
            Line ln = new Line();

            try {
                ln.setDescripcion(description);
                ln.setFechaAlta(DateTime.getToday());
                ln.setFechaBaja(dropDate);
                ln.setFechaDisponibilidadLinea(availableDate);
                ds.saveLine(ln);
            } catch (Exception e) {
                parameters.put("ERROR", e.getMessage());
                e.printStackTrace();
            }
        }

        return parameters.toString();
    }

    public static void createMany(JSONArray list) throws JSONException {
        for (int i = 0; i < list.length(); i++) {
            instance.create((JSONObject) list.get(i));
        }
    }

    public String edit(JSONObject parameters) throws JSONException {
        int id = parameters.getInt("id");
        String list = parameters.getString("list");

        return parameters.toString();
    }

    public String remove(JSONObject parameters) throws JSONException {
        int id = parameters.getInt("id");
        try {
            ds.deleteLine(id);
        } catch (Exception exception) {
            System.out.println("SQL Error");
        }

        return parameters.toString();
    }

    public String getFormattedSuggestions(JSONObject parameters) throws JSONException {
        String searchWords = parameters.getString("searchWords");

        return "<ul><li>" + searchWords + "</li><li>dois</li></ul>";
    }

    public String search(JSONObject parameters) throws JSONException {
        Map mp = null;
        String jsonObj = "{\"render\" : \"true\" , \"items\": [";
        String searchWords = parameters.getString("postData");
        try {
            mp = ds.retrieveLinesLike(searchWords);
        } catch (Exception exception) {
            System.out.println("Error SQL");
        }
        Collection col = mp.values();
        Iterator it = col.iterator();
        while (it.hasNext()) {
            Line ln = (Line) it.next();
            jsonObj += "{\"id\" : \"" + ln.getID() + "\", \"description\" : \"" + ln.getDescripcion() + "\", \"fechaAlta\" : \"" + ln.getFechaAlta() + "\", \"dropDate\" : \"" + ln.getFechaBaja() + "\", \"avaliableDate\" : \"" + ln.getFechaDisponibilidadLinea() + "\"}, ";
        }
        jsonObj = jsonObj.substring(0, jsonObj.length()); //Corta la ultima coma
        jsonObj += "]}";//Cierra el string\

        return jsonObj;
    //return searchWords + "";
    }
    //URGENCIA!!!
    public String advancedSearch(JSONObject parameters) throws JSONException {
        List<Line> lst;
        String equipment = parameters.getString("equipment");
        String maintenance = parameters.getString("maintenance");
        String createdFrom = parameters.getString("created-from");
        String createdTo = parameters.getString("created-to");
        String droppedFrom = parameters.getString("dropped-from");
        String droppedTo = parameters.getString("dropped-to");
        String availableFrom = parameters.getString("available-from");
        String availableTo = parameters.getString("available-to");
        String vacantFrom = parameters.getString("vacant-from");
        String vacantTo = parameters.getString("vacant-to");
        String occupiedFrom = parameters.getString("occupied-from");
        String occupiedTo = parameters.getString("occupied-to");
        try {
        } catch (Exception exception) {
        }

        return equipment;
    }

    public String read(JSONObject parameters) throws JSONException {
        String filter = parameters.getString("filter");
        String order = parameters.getString("order");

        List<Line> list = new ArrayList();

        try {
            list = ds.retrieveLines();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return render(list);
    }

    private String render(List<Line> list) throws JSONException {
        JSONObject jsonResponse = new JSONObject();

        jsonResponse.put("render", true);
        jsonResponse.put("items", list);

        return jsonResponse.toString();
    }
}
